package com.ungs.bo.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import com.ungs.bo.OrdenTrabajoBO;
import com.ungs.dao.OrdenTrabajoDAO;
import com.ungs.dao.impl.OrdenTrabajoDAOImpl;
import com.ungs.entities.Material;
import com.ungs.entities.OrdenTrabajo;
import com.ungs.entities.ProcesoXOrden;
import com.ungs.utils.Constantes;

public class OrdenTrabajoBOImpl extends EntidadBOImpl<OrdenTrabajo> implements
		OrdenTrabajoBO {

	private OrdenTrabajoDAO ordenTrabajoDAO = new OrdenTrabajoDAOImpl();

	@Override
	public OrdenTrabajo getUltimaOrdenTrabajo() {
		return ordenTrabajoDAO.getUltimaOrdenTrabajo();
	}

	@Override
	public Long getUltimoId() {
		Long idOrdenTrabajo = null;
		OrdenTrabajo ordenTrabajo = ordenTrabajoDAO.getUltimaOrdenTrabajo();

		if (ordenTrabajo != null) {
			idOrdenTrabajo = ordenTrabajo.getId();
		}

		return idOrdenTrabajo;
	}

	@Override
	public List<OrdenTrabajo> getOrdenTrabajoSinFinalizar() {
		return ordenTrabajoDAO.getOrdenTrabajoSinFinalizar();
	}

	@Override
	public OrdenTrabajo getOrdenTrabajoByNumIdentificatorio(
			String numIdentificatorio) {
		return ordenTrabajoDAO
				.getOrdenTrabajoByNumIdentificatorio(numIdentificatorio);
	}

	@Override
	public List<Material> getMaterialesByOrdenTrabajo(OrdenTrabajo ordenTrabajo) {
		return ordenTrabajoDAO.getMaterialesByOrdenTrabajo(ordenTrabajo);
	}

	@Override
	public List<ProcesoXOrden> getProcesosXOrdenByOrdenTrabajo(
			OrdenTrabajo ordenTrabajo) {
		return ordenTrabajoDAO.getProcesosXOrdenByOrdenTrabajo(ordenTrabajo);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<OrdenTrabajo> getAllOrdenTrabajo() {
		List<OrdenTrabajo> ordenTrabajoList = (List<OrdenTrabajo>) getAll(OrdenTrabajo.class);
		List<OrdenTrabajo> ordenTrabajoReturn = new ArrayList<OrdenTrabajo>();

		logger.info("Obteniendo lista de orden trabajo con alta logica");
		for (OrdenTrabajo ordenTrabajo : ordenTrabajoList) {
			if (ordenTrabajo.getEstadoLogico().equals(Constantes.ALTA)) {
				ordenTrabajoReturn.add(ordenTrabajo);
			}
		}

		return ordenTrabajoReturn;
	}

	@Override
	public void eliminarOrdenTrabajo(OrdenTrabajo ordenTrabajo) {
		logger.info("Baja logica ordenTrabajo: " + ordenTrabajo.getId());
		ordenTrabajo.setEstadoLogico(Constantes.BAJA);
		actualizar(ordenTrabajo);

	}

	@Override
	public String estadoProcesoOT(OrdenTrabajo ordenTrabajo) {
		String estadoOT = "";
		String procesoEnCurso = "";
		boolean hayProcesoEnCurso = false;
		if (!ordenTrabajo.getEstado().equals(Constantes.ESTADO_PENDIENTE)) {
			logger.info("Obteniendo el estado de la OT");
			// Si la orden de trabajo comenzo
			List<ProcesoXOrden> procesoXOrdenList = ordenTrabajoDAO
					.getProcesosXOrdenByOrdenTrabajo(ordenTrabajo);

			int proceso = 0;
			for (ProcesoXOrden procesoXOrden : procesoXOrdenList) {
				if (procesoXOrden.getEstado()
						.equals(Constantes.ESTADO_EN_CURSO)) {
					// Si hay un proceso en curso se muestra
					procesoEnCurso = procesoXOrden.getProceso()
							.getDescripcion();
					hayProcesoEnCurso = true;
				}

				if (procesoXOrden.getEstado().equals(
						Constantes.ESTADO_FINALIZADO)) {
					// Si no hay procesos en curso se muestra el siguiente
					if ((procesoXOrdenList.size() - 1) != proceso) {
						// Si es distinto del ultimo proceso.
						procesoEnCurso = procesoXOrdenList.get(proceso + 1)
								.getProceso().getDescripcion();
						hayProcesoEnCurso = true;
					} else {
						hayProcesoEnCurso = false;
					}
				}

				proceso++;
			}

			if (!hayProcesoEnCurso) {
				// Si no se comenzo ningun proceso se muestra el primero
				procesoEnCurso = procesoXOrdenList.get(0).getProceso()
						.getDescripcion();
				estadoOT = ordenTrabajo.getEstado();
			} else {
				// Se muestra el estado de la orden de trabajo y el proceso en
				// curso.
				estadoOT = ordenTrabajo.getEstado() + ": " + procesoEnCurso;
			}
		} else {
			// Si la orden de trabajo esta pendiente
			estadoOT = ordenTrabajo.getEstado();
		}

		return estadoOT;
	}

	@Override
	public List<Calendar> getFechasOrdenTrabajo() {
		List<OrdenTrabajo> ordenTrabajoList = new ArrayList<OrdenTrabajo>();
		List<Calendar> calendarList = new ArrayList<Calendar>();
		ordenTrabajoList = getOrdenTrabajoSinFinalizar();

		logger.info("Obteniendo las fechas prometidas de la OT sin finalizar");
		for (OrdenTrabajo ordenTrabajo : ordenTrabajoList) {
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(ordenTrabajo.getFechaPrometida());
			calendarList.add(calendar);
		}

		return calendarList;
	}

	@Override
	public List<OrdenTrabajo> getOrdenTrabajoByFecha(Date fechaBusqueda) {
		List<OrdenTrabajo> ordenTrabajoList = getOrdenTrabajoSinFinalizar();
		List<OrdenTrabajo> ordenTrabajoReturn = new ArrayList<OrdenTrabajo>();

		Calendar calendarDesde = Calendar.getInstance();
		calendarDesde.setTime(fechaBusqueda);
		calendarDesde.set(Calendar.HOUR_OF_DAY, 0);
		calendarDesde.set(Calendar.MINUTE, 1);
		calendarDesde.set(Calendar.SECOND, 0);

		Calendar calendarHasta = Calendar.getInstance();
		calendarHasta.setTime(fechaBusqueda);
		calendarHasta.set(Calendar.HOUR_OF_DAY, 23);
		calendarHasta.set(Calendar.MINUTE, 59);
		calendarHasta.set(Calendar.SECOND, 59);

		logger.info("Obteniendo lista de OT entre fechas");
		for (OrdenTrabajo ordenTrabajo : ordenTrabajoList) {
			Date fechaOrdenTrabajo = ordenTrabajo.getFechaPrometida();
			Calendar calendarOrdenTrabajo = Calendar.getInstance();
			calendarOrdenTrabajo.setTime(fechaOrdenTrabajo);

			if (calendarDesde.compareTo(calendarOrdenTrabajo) < 0
					&& calendarHasta.compareTo(calendarOrdenTrabajo) > 0) {
				ordenTrabajoReturn.add(ordenTrabajo);
			}
		}

		return ordenTrabajoReturn;
	}

	@Override
	public List<OrdenTrabajo> getOrdenTrabajoEnCurso() {
		List<OrdenTrabajo> ordenTrabajoSinFinalizar = ordenTrabajoDAO
				.getOrdenTrabajoSinFinalizar();
		List<OrdenTrabajo> ordenTrabajoReturn = new ArrayList<OrdenTrabajo>();

		logger.info("Obteniendo lista de OT en curso");
		for (OrdenTrabajo ordenTrabajo : ordenTrabajoSinFinalizar) {
			if (ordenTrabajo.getEstado().equals(Constantes.ESTADO_EN_CURSO)) {
				ordenTrabajoReturn.add(ordenTrabajo);
			}
		}
		return ordenTrabajoReturn;
	}

	@Override
	public List<OrdenTrabajo> getOrdenTrabajoUrgente() {
		return ordenTrabajoDAO.getOrdenTrabajoUrgente();
	}

}
